Este es nuestro informe para la presentación del día 18 de diciembre. Aquí comentaremos de que trata nuestro trabajo y las transformaciones que hemos realizado, así como, el código de estas y los diferentes paquetes utilizados.

1. INTRODUCCIÓN

Nuestro trabajo consiste en la manipulación de datos del INE en lo referente a nombres y apellidos en España. Para esto, descargaremos desde R los datos de frecuencia de nombres y apellidos españoles del INE y también descargaremos un excel de forma manual de la distribución geográfica provincial de nuestro nombre y primer apellido.

2. CARGAMOS DATOS Y PAQUETES

Vamos a cargar diferentes paquetes que iremos utilizando a lo largo del trabajo.


library(tidyverse)
library(readxl)
library(reactable)
library(ggplot2)
library(stringi)
library(ggThemeAssist)
library(plotly)

Ahora descargaremos los diferentes informes para manipularlos y los transformaremos para poder hacerlos visibles. Tendremos 2 dataframes de apellidos, uno para frecuencia >100 y otros para frecuencia <100 y >20. Así mismo, tendremos 2 dataframes de nombres, uno para hombres y otro para mujeres.

#APELLIDOS
#- descargamos los datos en "./Datos/frecuencia.xls"
url <- "https://www.ine.es/daco/daco42/nombyapel/apellidos_frecuencia.xls"
archivo_de_destino <- here::here("Datos", "frecuencia.xls")
download.file(url, archivo_de_destino)

#- Vamos a importar los datos tipo excel con la función readxl y mediante el sheet=1 cogeremos la HOJA 1 del excel y mediante el range, cogeremos desde el Orden hasta el último total, ya que, si importamos directamente el EXCEL tendriamos que eliminar algunas de las primeras filas, por lo que, mediante esto ya lo tenemos como queremos.
df_apellidos1 <- read_excel ("./Datos/frecuencia.xls", sheet=1, range="A5:E25798")
df_apellidos2 <- read_excel ("./Datos/frecuencia.xls", sheet=2, range="A5:E50393")


#NOMBRES
url2 <- "https://www.ine.es/daco/daco42/nombyapel/nombres_por_edad_media.xls"
archivo_de_destino2 <- here::here("Datos", "frecuencianombre.xls")
download.file(url2, archivo_de_destino2)

# Vamos a importar los datos tipo excel con la función readxl y mediante el sheet=1 cogeremos la HOJA 1 del excel y mediante el range, cogeremos desde el Orden hasta el último total, ya que, si importamos directamente el EXCEL tendriamos que eliminar algunas de las primeras filas, por lo que, mediante esto ya lo tenemos como queremos.
df_nombre1 <- read_excel ("./Datos/frecuencianombre.xls", sheet=1, range="A7:D25790")
df_nombre <- read_excel ("./Datos/frecuencianombre.xls", sheet=2, range="A7:D26499")



#Daniel y Laura frecuencia y provincias
df_Daniel <- read_excel ("./Datos/Daniel_Laura.xlsx", sheet=1)
df_Laura <- read_excel ("./Datos/Daniel_Laura.xlsx", sheet=2)

3. MODIFICAMOS NUESTROS DATAFRAMES

Si abriesemos los dataframes de apellidos, vemos que aparecen varias variables que se llaman “Total” las cuales van referidas a algo. Vamos a modificar los nombre por aquello a lo que correspondes esos “totales”.


#Modificamos los nombres de las columnas que se llaman total, por aquello a lo que le corresponde (es un total, pero un total de algo, lo llamaremos conforme ese ALGO)
df_apellidos1 <- df_apellidos1 %>% rename(Frec_1er_Apellido = Total...3,
  Frec_2o_Apellido= Total...4,
  Frec_Ambos_Apellidos= Total...5)

df_apellidos2 <- df_apellidos2 %>% rename(Frec_1er_Apellido = Total...3,
  Frec_2o_Apellido= Total...4,
  Frec_Ambos_Apellidos= Total...5)


df_apellidosmodif <- suppressWarnings(transform(df_apellidos2, Frec_2o_Apellido= as.numeric(Frec_2o_Apellido),
  Frec_Ambos_Apellidos=as.numeric(Frec_Ambos_Apellidos)
  )
  )

4. TRANSFORMACIONES

4.1 TABLAS

Ahora, vamos a manipular nuestros dataframes para hacer ciertas construcciones, en este caso empezaremos con unas tablas. Estas, van a recoger los nombres y apellidos agrupados por la letra que empiecen y con distintos colores de celda dependiendo la frecuencia, siendo verde frecuencia alta, naranja frecuencia media y rojo frecuencia baja, es decir, poco frecuentes.

Primero de todo, necesitaremos unir ambas tablas, tanto de nombres como de apellidos en una sola.

#APELLIDOS
df_apellidos_conjuntos <- full_join(df_apellidos1, df_apellidosmodif, by= c("Orden","Apellido","Frec_1er_Apellido","Frec_2o_Apellido","Frec_Ambos_Apellidos"))

df_apellidos_conjuntos2 <- df_apellidos_conjuntos %>%
  mutate(Letra= stri_sub(Apellido,1,1)) %>%
  arrange(Letra)


#NOMBRES
df_nombreH<- df_nombre1 %>%
  mutate(Sexo="Hombre") %>%
  rename(Edad= `Edad Media (*)`)%>%
  select(-c(Orden))

df_nombreM <- df_nombre %>%
  mutate(Sexo="Mujer") %>%
  rename(Edad= `Edad Media (*)`) %>%
  select(-c(Orden))


df_NombresJuntos<- full_join(df_nombreH, df_nombreM, by= c("Nombre","Frecuencia","Edad","Sexo")) %>% arrange(desc(Frecuencia))

df_NombresJuntos2 <- df_NombresJuntos %>%
  mutate(Letra= stri_sub(Nombre,1,1)) %>%
  arrange(Letra)

De esta forma, haremos una tabla con buscador de NOMBRES y otra para APELLIDOS

4.2. GRÁFICAS

Para los gráficos, haremos 3 gráficos de barras. El primero estará relacionado con los 10 apellidos más frecuentes, el segundo con los 10 nombres más frecuentes y el tercero será un gráfico de los 10 nombres menos comunes y los 10 que más.

Primero, necesitaremos transformar los datos

#APELLIDOS
df_apellidos <- df_apellidos1 %>% select(Apellido, Frec_1er_Apellido, Frec_2o_Apellido) %>% mutate(Frec_Total= Frec_1er_Apellido + Frec_2o_Apellido) %>% slice_max(Frec_Total, n=10) %>% mutate(Apellido = forcats::as_factor(Apellido)) %>% mutate(Apellido = forcats::fct_reorder(Apellido, Frec_Total))


p <- ggplot(df_apellidos, aes(Apellido, Frec_Total)) + geom_col(fill = "steelblue") + coord_flip()


#NOMBRES
df_nombres <- full_join(df_nombre, df_nombre1)

df_nombres3 <-df_nombres %>% select(Nombre, Frecuencia) %>% slice_max(Frecuencia, n=10) %>% mutate(Nombre = forcats::as_factor(Nombre)) %>% mutate(Nombre = forcats::fct_reorder(Nombre, Frecuencia))

s <- ggplot(df_nombres3, aes(Nombre, Frecuencia)) + geom_col(fill = "steelblue") + coord_flip()


#10 MÁS FRECUENTES Y 10 QUE MENOS
df_nombres_edadmedia <- df_nombres %>% select(Nombre, `Edad Media (*)`) %>% arrange(desc(`Edad Media (*)`)) %>%
  slice(c(1,2,3,4,5,6,7,8,9,10,n()-9,n()-8,n()-7,n()-6,n()-5,n()-4,n()-3,n()-2,n()-1, n()))%>%
  mutate(Nombre = forcats::as_factor(Nombre)) %>% mutate(Nombre = forcats::fct_reorder(Nombre, `Edad Media (*)`))

r <- ggplot(df_nombres_edadmedia, aes(Nombre, `Edad Media (*)`)) + geom_col(fill="steelblue") + coord_flip()

Mostramos los gráficos:

4.3. MAPAS

Cargaremos primero las geometrías de la carpeta Datos

load("./Datos/geometrias_clase_10.RData")

Y ahora haremos un mapa para la frecuencia por provincias del nombre de Daniel:


#Hacemos un mapa de coropletas del país para el total del nombre "Daniel"
dfDaniel <- full_join(df_Daniel, Provincias, by = c("Provincia" = "NombreProv"))

Y ahora otro mapa para la frecuencia por provincias del nombre de Laura:


#Hacemos otro mapa de coropletas para el total del nombre "Laura".
dfLaura<-full_join(df_Laura, Provincias, by = c("Provincia" = "NombreProv"))

5. Conclusión

Las conclusiones son …

Referencias

Para la realización del trabajo he utilizado:




Para acabar este chunk para incluir tu session info:

sessioninfo::session_info() %>% details::details(summary = 'current session info') 

current session info


─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 4.0.2 (2020-06-22)
 os       macOS Catalina 10.15.7      
 system   x86_64, darwin17.0          
 ui       X11                         
 language (EN)                        
 collate  es_ES.UTF-8                 
 ctype    es_ES.UTF-8                 
 tz       Europe/Madrid               
 date     2020-12-11                  

─ Packages ───────────────────────────────────────────────────────────────────
 package       * version    date       lib
 assertthat      0.2.1      2019-03-21 [1]
 backports       1.1.10     2020-09-15 [1]
 base64enc       0.1-3      2015-07-28 [1]
 blob            1.2.1      2020-01-20 [1]
 broom           0.7.0      2020-07-09 [1]
 cellranger      1.1.0      2016-07-27 [1]
 class           7.3-17     2020-04-26 [1]
 classInt        0.4-3      2020-04-07 [1]
 cli             2.0.2      2020-02-28 [1]
 colorspace      1.4-1      2019-03-18 [1]
 crayon          1.3.4      2017-09-16 [1]
 crosstalk       1.1.0.1    2020-03-13 [1]
 data.table      1.13.0     2020-07-24 [1]
 DBI             1.1.0      2019-12-15 [1]
 dbplyr          1.4.4      2020-05-27 [1]
 digest          0.6.25     2020-02-23 [1]
 dplyr         * 1.0.2      2020-08-18 [1]
 e1071           1.7-3      2019-11-26 [1]
 ellipsis        0.3.1      2020-05-15 [1]
 evaluate        0.14       2019-05-28 [1]
 fansi           0.4.1      2020-01-08 [1]
 farver          2.0.3      2020-01-16 [1]
 fastmap         1.0.1      2019-10-08 [1]
 forcats       * 0.5.0      2020-03-01 [1]
 formatR         1.7        2019-06-11 [1]
 fs              1.5.0      2020-07-31 [1]
 generics        0.1.0      2020-10-31 [1]
 ggplot2       * 3.3.2      2020-06-19 [1]
 ggrepel       * 0.8.2      2020-03-08 [1]
 ggThemeAssist * 0.1.5.9001 2020-11-13 [1]
 glue            1.4.2      2020-08-27 [1]
 gtable          0.3.0      2019-03-25 [1]
 haven           2.3.1      2020-06-01 [1]
 here            0.1        2017-05-28 [1]
 hms             0.5.3      2020-01-08 [1]
 htmltools       0.5.0      2020-06-16 [1]
 htmlwidgets     1.5.1      2019-10-08 [1]
 httpuv          1.5.4      2020-06-06 [1]
 httr            1.4.2      2020-07-20 [1]
 jsonlite        1.7.1      2020-09-07 [1]
 KernSmooth      2.23-17    2020-04-26 [1]
 klippy        * 0.0.0.9500 2020-11-17 [1]
 knitr         * 1.29       2020-06-23 [1]
 labeling        0.3        2014-08-23 [1]
 later           1.1.0.1    2020-06-05 [1]
 lazyeval        0.2.2      2019-03-15 [1]
 lifecycle       0.2.0      2020-03-06 [1]
 lubridate       1.7.9      2020-06-08 [1]
 magrittr        1.5        2014-11-22 [1]
 mime            0.9        2020-02-04 [1]
 miniUI          0.1.1.1    2018-05-18 [1]
 modelr          0.1.8      2020-05-19 [1]
 munsell         0.5.0      2018-06-12 [1]
 patchwork     * 1.1.0      2020-11-09 [1]
 pillar          1.4.6      2020-07-10 [1]
 pkgconfig       2.0.3      2019-09-22 [1]
 plotly        * 4.9.2.1    2020-04-04 [1]
 promises        1.1.1      2020-06-09 [1]
 purrr         * 0.3.4      2020-04-17 [1]
 R6              2.4.1      2019-11-12 [1]
 Rcpp            1.0.5      2020-07-06 [1]
 reactable     * 0.2.3      2020-10-04 [1]
 reactR          0.4.3      2020-07-12 [1]
 readr         * 1.3.1      2018-12-21 [1]
 readxl        * 1.3.1      2019-03-13 [1]
 rematch         1.0.1      2016-04-21 [1]
 reprex          0.3.0      2019-05-16 [1]
 rlang           0.4.7      2020-07-09 [1]
 rmarkdown       2.3        2020-06-18 [1]
 rprojroot       1.3-2      2018-01-03 [1]
 rstudioapi      0.11       2020-02-07 [1]
 rvest           0.3.6      2020-07-25 [1]
 scales          1.1.1      2020-05-11 [1]
 sessioninfo     1.1.1      2018-11-05 [1]
 sf            * 0.9-6      2020-09-13 [1]
 shiny           1.5.0      2020-06-23 [1]
 stringi       * 1.5.3      2020-09-09 [1]
 stringr       * 1.4.0      2019-02-10 [1]
 tibble        * 3.0.3      2020-07-10 [1]
 tidyr         * 1.1.2      2020-08-27 [1]
 tidyselect      1.1.0      2020-05-11 [1]
 tidyverse     * 1.3.0      2019-11-21 [1]
 units           0.6-7      2020-06-13 [1]
 vctrs           0.3.4      2020-08-29 [1]
 viridisLite     0.3.0      2018-02-01 [1]
 withr           2.2.0      2020-04-20 [1]
 xfun            0.17       2020-09-09 [1]
 xml2            1.3.2      2020-04-23 [1]
 xtable          1.8-4      2019-04-21 [1]
 yaml            2.2.1      2020-02-01 [1]
 source                                   
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.1)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 Github (calligross/ggthemeassist@35b720f)
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 Github (rlesur/klippy@378c247)           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.1)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           
 CRAN (R 4.0.2)                           

[1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library


LS0tCnRpdGxlOiAiUGxhbnRpbGxhIHBhcmEgbnVlc3RybyBpbmZvcm1lIgphdXRob3I6ICJEYW5pZWwgQ2FzaW5vLCBMYXVyYSBCb3Jyw6FzIHkgTGF1cmEgQWxiZXJ0IgpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjAgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBwYXBlcgogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZSAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzIAogICAgdG9jX2Zsb2F0OiAKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBkZl9wcmludDoga2FibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3IgcGFja2FnZXMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoa2xpcHB5KSAgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShyZWFjdGFibGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KGdnVGhlbWVBc3Npc3QpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KHNmKQpgYGAKCmBgYHtyIGNodW5rLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICNyZXN1bHRzID0gImhvbGQiLAogICAgICAgICAgICAgICAgICAgICAgY2FjaGUgPSBGQUxTRSwgY2FjaGUucGF0aCA9ICIvY2FjaGVzLyIsIGNvbW1lbnQgPSAiIz4iLAogICAgICAgICAgICAgICAgICAgICAgI2ZpZy53aWR0aCA9IDcsICNmaWcuaGVpZ2h0PSA3LCAgIAogICAgICAgICAgICAgICAgICAgICAgI291dC53aWR0aCA9IDcsIG91dC5oZWlnaHQgPSA3LAogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCAgZmlnLnNob3cgPSAiaG9sZCIsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYXNwID0gNy85LCBvdXQud2lkdGggPSAiNjAlIiwgZmlnLmFsaWduID0gImNlbnRlciIpCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpCmBgYAoKYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgCm9wdGlvbnMoInlhbWwuZXZhbC5leHByIiA9IFRSVUUpIApgYGAKCgpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0Ka2xpcHB5OjprbGlwcHkocG9zaXRpb24gPSBjKCJ0b3AiLCAicmlnaHQiKSkgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tCgo8YnI+CgpFc3RlIGVzIG51ZXN0cm8gaW5mb3JtZSBwYXJhIGxhIHByZXNlbnRhY2nDs24gZGVsIGTDrWEgMTggZGUgZGljaWVtYnJlLiBBcXXDrSBjb21lbnRhcmVtb3MgZGUgcXVlIHRyYXRhIG51ZXN0cm8gdHJhYmFqbyB5IGxhcyB0cmFuc2Zvcm1hY2lvbmVzIHF1ZSBoZW1vcyByZWFsaXphZG8sIGFzw60gY29tbywgZWwgY8OzZGlnbyBkZSBlc3RhcyB5IGxvcyBkaWZlcmVudGVzIHBhcXVldGVzIHV0aWxpemFkb3MuCgojIyAxLiBJTlRST0RVQ0NJw5NOCgpOdWVzdHJvIHRyYWJham8gY29uc2lzdGUgZW4gbGEgbWFuaXB1bGFjacOzbiBkZSBkYXRvcyBkZWwgSU5FIGVuIGxvIHJlZmVyZW50ZSBhIG5vbWJyZXMgeSBhcGVsbGlkb3MgZW4gRXNwYcOxYS4gClBhcmEgZXN0bywgZGVzY2FyZ2FyZW1vcyBkZXNkZSBSIGxvcyBkYXRvcyBkZSBmcmVjdWVuY2lhIGRlIG5vbWJyZXMgeSBhcGVsbGlkb3MgZXNwYcOxb2xlcyBkZWwgSU5FIHkgdGFtYmnDqW4gZGVzY2FyZ2FyZW1vcyB1biBleGNlbCBkZSBmb3JtYSBtYW51YWwgZGUgbGEgZGlzdHJpYnVjacOzbiBnZW9ncsOhZmljYSBwcm92aW5jaWFsIGRlIG51ZXN0cm8gbm9tYnJlIHkgcHJpbWVyIGFwZWxsaWRvLgoKCiMjIDIuICBDQVJHQU1PUyBEQVRPUyBZIFBBUVVFVEVTCgpWYW1vcyBhIGNhcmdhciBkaWZlcmVudGVzIHBhcXVldGVzIHF1ZSBpcmVtb3MgdXRpbGl6YW5kbyBhIGxvIGxhcmdvIGRlbCB0cmFiYWpvLgoKYGBge3IgZWNobz1UUlVFLCBldmFsPSBGQUxTRX0KCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShyZWFjdGFibGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KGdnVGhlbWVBc3Npc3QpCmxpYnJhcnkocGxvdGx5KQoKYGBgCgpBaG9yYSBkZXNjYXJnYXJlbW9zIGxvcyBkaWZlcmVudGVzIGluZm9ybWVzIHBhcmEgbWFuaXB1bGFybG9zIHkgbG9zIHRyYW5zZm9ybWFyZW1vcyBwYXJhIHBvZGVyIGhhY2VybG9zIHZpc2libGVzLiAKVGVuZHJlbW9zIDIgZGF0YWZyYW1lcyBkZSBhcGVsbGlkb3MsIHVubyBwYXJhIGZyZWN1ZW5jaWEgPjEwMCB5IG90cm9zIHBhcmEgZnJlY3VlbmNpYSA8MTAwIHkgPjIwLgpBc8OtIG1pc21vLCB0ZW5kcmVtb3MgMiBkYXRhZnJhbWVzIGRlIG5vbWJyZXMsIHVubyBwYXJhIGhvbWJyZXMgeSBvdHJvIHBhcmEgbXVqZXJlcy4KYGBge3IgZWNobyA9IFRSVUUsIGV2YWw9VFJVRX0KI0FQRUxMSURPUwojLSBkZXNjYXJnYW1vcyBsb3MgZGF0b3MgZW4gIi4vRGF0b3MvZnJlY3VlbmNpYS54bHMiCnVybCA8LSAiaHR0cHM6Ly93d3cuaW5lLmVzL2RhY28vZGFjbzQyL25vbWJ5YXBlbC9hcGVsbGlkb3NfZnJlY3VlbmNpYS54bHMiCmFyY2hpdm9fZGVfZGVzdGlubyA8LSBoZXJlOjpoZXJlKCJEYXRvcyIsICJmcmVjdWVuY2lhLnhscyIpCmRvd25sb2FkLmZpbGUodXJsLCBhcmNoaXZvX2RlX2Rlc3Rpbm8pCgojLSBWYW1vcyBhIGltcG9ydGFyIGxvcyBkYXRvcyB0aXBvIGV4Y2VsIGNvbiBsYSBmdW5jacOzbiByZWFkeGwgeSBtZWRpYW50ZSBlbCBzaGVldD0xIGNvZ2VyZW1vcyBsYSBIT0pBIDEgZGVsIGV4Y2VsIHkgbWVkaWFudGUgZWwgcmFuZ2UsIGNvZ2VyZW1vcyBkZXNkZSBlbCBPcmRlbiBoYXN0YSBlbCDDumx0aW1vIHRvdGFsLCB5YSBxdWUsIHNpIGltcG9ydGFtb3MgZGlyZWN0YW1lbnRlIGVsIEVYQ0VMIHRlbmRyaWFtb3MgcXVlIGVsaW1pbmFyIGFsZ3VuYXMgZGUgbGFzIHByaW1lcmFzIGZpbGFzLCBwb3IgbG8gcXVlLCBtZWRpYW50ZSBlc3RvIHlhIGxvIHRlbmVtb3MgY29tbyBxdWVyZW1vcy4KZGZfYXBlbGxpZG9zMSA8LSByZWFkX2V4Y2VsICgiLi9EYXRvcy9mcmVjdWVuY2lhLnhscyIsIHNoZWV0PTEsIHJhbmdlPSJBNTpFMjU3OTgiKQpkZl9hcGVsbGlkb3MyIDwtIHJlYWRfZXhjZWwgKCIuL0RhdG9zL2ZyZWN1ZW5jaWEueGxzIiwgc2hlZXQ9MiwgcmFuZ2U9IkE1OkU1MDM5MyIpCgoKI05PTUJSRVMKdXJsMiA8LSAiaHR0cHM6Ly93d3cuaW5lLmVzL2RhY28vZGFjbzQyL25vbWJ5YXBlbC9ub21icmVzX3Bvcl9lZGFkX21lZGlhLnhscyIKYXJjaGl2b19kZV9kZXN0aW5vMiA8LSBoZXJlOjpoZXJlKCJEYXRvcyIsICJmcmVjdWVuY2lhbm9tYnJlLnhscyIpCmRvd25sb2FkLmZpbGUodXJsMiwgYXJjaGl2b19kZV9kZXN0aW5vMikKCiMgVmFtb3MgYSBpbXBvcnRhciBsb3MgZGF0b3MgdGlwbyBleGNlbCBjb24gbGEgZnVuY2nDs24gcmVhZHhsIHkgbWVkaWFudGUgZWwgc2hlZXQ9MSBjb2dlcmVtb3MgbGEgSE9KQSAxIGRlbCBleGNlbCB5IG1lZGlhbnRlIGVsIHJhbmdlLCBjb2dlcmVtb3MgZGVzZGUgZWwgT3JkZW4gaGFzdGEgZWwgw7psdGltbyB0b3RhbCwgeWEgcXVlLCBzaSBpbXBvcnRhbW9zIGRpcmVjdGFtZW50ZSBlbCBFWENFTCB0ZW5kcmlhbW9zIHF1ZSBlbGltaW5hciBhbGd1bmFzIGRlIGxhcyBwcmltZXJhcyBmaWxhcywgcG9yIGxvIHF1ZSwgbWVkaWFudGUgZXN0byB5YSBsbyB0ZW5lbW9zIGNvbW8gcXVlcmVtb3MuCmRmX25vbWJyZTEgPC0gcmVhZF9leGNlbCAoIi4vRGF0b3MvZnJlY3VlbmNpYW5vbWJyZS54bHMiLCBzaGVldD0xLCByYW5nZT0iQTc6RDI1NzkwIikKZGZfbm9tYnJlIDwtIHJlYWRfZXhjZWwgKCIuL0RhdG9zL2ZyZWN1ZW5jaWFub21icmUueGxzIiwgc2hlZXQ9MiwgcmFuZ2U9IkE3OkQyNjQ5OSIpCgoKCiNEYW5pZWwgeSBMYXVyYSBmcmVjdWVuY2lhIHkgcHJvdmluY2lhcwpkZl9EYW5pZWwgPC0gcmVhZF9leGNlbCAoIi4vRGF0b3MvRGFuaWVsX0xhdXJhLnhsc3giLCBzaGVldD0xKQpkZl9MYXVyYSA8LSByZWFkX2V4Y2VsICgiLi9EYXRvcy9EYW5pZWxfTGF1cmEueGxzeCIsIHNoZWV0PTIpCgoKCgpgYGAKCgojIyAzLiBNT0RJRklDQU1PUyBOVUVTVFJPUyBEQVRBRlJBTUVTClNpIGFicmllc2Vtb3MgbG9zIGRhdGFmcmFtZXMgZGUgYXBlbGxpZG9zLCB2ZW1vcyBxdWUgYXBhcmVjZW4gdmFyaWFzIHZhcmlhYmxlcyBxdWUgc2UgbGxhbWFuICJUb3RhbCIgbGFzIGN1YWxlcyB2YW4gcmVmZXJpZGFzIGEgYWxnby4gVmFtb3MgYSBtb2RpZmljYXIgbG9zIG5vbWJyZSBwb3IgYXF1ZWxsbyBhIGxvIHF1ZSBjb3JyZXNwb25kZXMgZXNvcyAidG90YWxlcyIuCmBgYHtyIGVjaG8gPSBUUlVFLCBldmFsPVRSVUV9CgojTW9kaWZpY2Ftb3MgbG9zIG5vbWJyZXMgZGUgbGFzIGNvbHVtbmFzIHF1ZSBzZSBsbGFtYW4gdG90YWwsIHBvciBhcXVlbGxvIGEgbG8gcXVlIGxlIGNvcnJlc3BvbmRlIChlcyB1biB0b3RhbCwgcGVybyB1biB0b3RhbCBkZSBhbGdvLCBsbyBsbGFtYXJlbW9zIGNvbmZvcm1lIGVzZSBBTEdPKQpkZl9hcGVsbGlkb3MxIDwtIGRmX2FwZWxsaWRvczEgJT4lIHJlbmFtZShGcmVjXzFlcl9BcGVsbGlkbyA9IFRvdGFsLi4uMywKICBGcmVjXzJvX0FwZWxsaWRvPSBUb3RhbC4uLjQsCiAgRnJlY19BbWJvc19BcGVsbGlkb3M9IFRvdGFsLi4uNSkKCmRmX2FwZWxsaWRvczIgPC0gZGZfYXBlbGxpZG9zMiAlPiUgcmVuYW1lKEZyZWNfMWVyX0FwZWxsaWRvID0gVG90YWwuLi4zLAogIEZyZWNfMm9fQXBlbGxpZG89IFRvdGFsLi4uNCwKICBGcmVjX0FtYm9zX0FwZWxsaWRvcz0gVG90YWwuLi41KQoKCmRmX2FwZWxsaWRvc21vZGlmIDwtIHN1cHByZXNzV2FybmluZ3ModHJhbnNmb3JtKGRmX2FwZWxsaWRvczIsIEZyZWNfMm9fQXBlbGxpZG89IGFzLm51bWVyaWMoRnJlY18yb19BcGVsbGlkbyksCiAgRnJlY19BbWJvc19BcGVsbGlkb3M9YXMubnVtZXJpYyhGcmVjX0FtYm9zX0FwZWxsaWRvcykKICApCiAgKQpgYGAKCiMjIDQuIFRSQU5TRk9STUFDSU9ORVMKIyMjIDQuMSBUQUJMQVMKQWhvcmEsIHZhbW9zIGEgbWFuaXB1bGFyIG51ZXN0cm9zIGRhdGFmcmFtZXMgcGFyYSBoYWNlciBjaWVydGFzIGNvbnN0cnVjY2lvbmVzLCBlbiBlc3RlIGNhc28gZW1wZXphcmVtb3MgY29uIHVuYXMgdGFibGFzLiBFc3RhcywgdmFuIGEgcmVjb2dlciBsb3Mgbm9tYnJlcyB5IGFwZWxsaWRvcyBhZ3J1cGFkb3MgcG9yIGxhIGxldHJhIHF1ZSBlbXBpZWNlbiB5IGNvbiBkaXN0aW50b3MgY29sb3JlcyBkZSBjZWxkYSBkZXBlbmRpZW5kbyBsYSBmcmVjdWVuY2lhLCBzaWVuZG8gdmVyZGUgZnJlY3VlbmNpYSBhbHRhLCBuYXJhbmphIGZyZWN1ZW5jaWEgbWVkaWEgeSByb2pvIGZyZWN1ZW5jaWEgYmFqYSwgZXMgZGVjaXIsIHBvY28gZnJlY3VlbnRlcy4KClByaW1lcm8gZGUgdG9kbywgbmVjZXNpdGFyZW1vcyB1bmlyIGFtYmFzIHRhYmxhcywgdGFudG8gZGUgbm9tYnJlcyBjb21vIGRlIGFwZWxsaWRvcyBlbiB1bmEgc29sYS4KCmBgYHtyIGVjaG89IFRSVUUsIGV2YWw9VFJVRX0KI0FQRUxMSURPUwpkZl9hcGVsbGlkb3NfY29uanVudG9zIDwtIGZ1bGxfam9pbihkZl9hcGVsbGlkb3MxLCBkZl9hcGVsbGlkb3Ntb2RpZiwgYnk9IGMoIk9yZGVuIiwiQXBlbGxpZG8iLCJGcmVjXzFlcl9BcGVsbGlkbyIsIkZyZWNfMm9fQXBlbGxpZG8iLCJGcmVjX0FtYm9zX0FwZWxsaWRvcyIpKQoKZGZfYXBlbGxpZG9zX2Nvbmp1bnRvczIgPC0gZGZfYXBlbGxpZG9zX2Nvbmp1bnRvcyAlPiUKICBtdXRhdGUoTGV0cmE9IHN0cmlfc3ViKEFwZWxsaWRvLDEsMSkpICU+JQogIGFycmFuZ2UoTGV0cmEpCgoKI05PTUJSRVMKZGZfbm9tYnJlSDwtIGRmX25vbWJyZTEgJT4lCiAgbXV0YXRlKFNleG89IkhvbWJyZSIpICU+JQogIHJlbmFtZShFZGFkPSBgRWRhZCBNZWRpYSAoKilgKSU+JQogIHNlbGVjdCgtYyhPcmRlbikpCgpkZl9ub21icmVNIDwtIGRmX25vbWJyZSAlPiUKICBtdXRhdGUoU2V4bz0iTXVqZXIiKSAlPiUKICByZW5hbWUoRWRhZD0gYEVkYWQgTWVkaWEgKCopYCkgJT4lCiAgc2VsZWN0KC1jKE9yZGVuKSkKCgpkZl9Ob21icmVzSnVudG9zPC0gZnVsbF9qb2luKGRmX25vbWJyZUgsIGRmX25vbWJyZU0sIGJ5PSBjKCJOb21icmUiLCJGcmVjdWVuY2lhIiwiRWRhZCIsIlNleG8iKSkgJT4lIGFycmFuZ2UoZGVzYyhGcmVjdWVuY2lhKSkKCmRmX05vbWJyZXNKdW50b3MyIDwtIGRmX05vbWJyZXNKdW50b3MgJT4lCiAgbXV0YXRlKExldHJhPSBzdHJpX3N1YihOb21icmUsMSwxKSkgJT4lCiAgYXJyYW5nZShMZXRyYSkKCmBgYAoKRGUgZXN0YSBmb3JtYSwgaGFyZW1vcyB1bmEgdGFibGEgY29uIGJ1c2NhZG9yIGRlIE5PTUJSRVMgeSBvdHJhIHBhcmEgQVBFTExJRE9TCgpgYGB7ciBlY2hvID0gRkFMU0UsIGV2YWw9VFJVRX0KCgpyZWFjdGFibGUoZGZfTm9tYnJlc0p1bnRvczIsCiAgY29sdW1ucz0gbGlzdChGcmVjdWVuY2lhPSBjb2xEZWYoCiAgc3R5bGUgPSBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIG5hbWUpIHsKICAgIGlmIChpcy5udW1lcmljKHZhbHVlKSAmJiB2YWx1ZSA+PSA1MDAwMCkgewogICAgICBsaXN0KGZvbnRXZWlnaHQgPSAiYm9sZCIsIGJhY2tncm91bmQgPSAicmdiYSgwLDI1NSwwLDAuMykiKQoKICAgIH1lbHNlIGlmIChpcy5udW1lcmljKHZhbHVlKSAmJiB2YWx1ZSA+PSAxMDAwMCApewogICAgICBsaXN0KGZvbnRXZWlnaHQ9ImJvbGQiLCBiYWNrZ3JvdW5kPSJyZ2JhKDI1NSwyNTUsMCwwLjMpIikKCiAgICB9ZWxzZXsKICAgICAgICBsaXN0KGZvbnRXZWlnaHQ9ImJvbGQiLCBiYWNrZ3JvdW5kPSJyZ2JhKDI1NSwwLDAsMC4zKSIpCiAgICAgIH0KICB9KQopLHJlc2l6YWJsZT0gVFJVRSwKICBzaG93UGFnZVNpemVPcHRpb25zID0gVFJVRSwKICBvdXRsaW5lZCA9IFRSVUUsCiAgc2VhcmNoYWJsZSA9IFRSVUUsCiAgZ3JvdXBCeSA9ICJMZXRyYSIsCiAgcGFnaW5hdGlvblR5cGUgPSAic2ltcGxlIiwKICBsYW5ndWFnZSA9IHJlYWN0YWJsZUxhbmcoCiAgICBzZWFyY2hQbGFjZWhvbGRlciA9ICJCdXNjYXIuLi4iLAogICAgbm9EYXRhID0gIk5vIGhheSByZXN1bHRhZG9zIiwKICAgIHBhZ2VJbmZvID0gIntyb3dTdGFydH0gZGUge3Jvd0VuZH0gZGUgbGFzIHtyb3dzfSBlbnRyYWRhcyIsCiAgICBwYWdlUHJldmlvdXMgPSAiXHUyNzZlIiwKICAgIHBhZ2VOZXh0ID0gIlx1Mjc2ZiIsCiAgICBwYWdlUHJldmlvdXNMYWJlbCA9ICJQw6FnaW5hIGFudGVyaW9yIiwKICAgIHBhZ2VOZXh0TGFiZWwgPSAiUMOhZ2luYSBzaWd1aWVudGUiCiAgKQogICkKCmBgYAoKYGBge3IgZWNobyA9IEZBTFNFLCBldmFsPVRSVUV9CgpyZWFjdGFibGUoCiAgZGZfYXBlbGxpZG9zX2Nvbmp1bnRvczIsCiAgZ3JvdXBCeSA9ICJMZXRyYSIsCiAgc2VhcmNoYWJsZSA9IFRSVUUsCiAgcGFnaW5hdGlvblR5cGUgPSAic2ltcGxlIiwKICBsYW5ndWFnZSA9IHJlYWN0YWJsZUxhbmcoCiAgICBzZWFyY2hQbGFjZWhvbGRlciA9ICJCdXNjYXIuLi4iLAogICAgbm9EYXRhID0gIk5vIGhheSByZXN1bHRhZG9zIiwKICAgIHBhZ2VJbmZvID0gIntyb3dTdGFydH0gZGUge3Jvd0VuZH0gZGUgbGFzIHtyb3dzfSBlbnRyYWRhcyIsCiAgICBwYWdlUHJldmlvdXMgPSAiXHUyNzZlIiwKICAgIHBhZ2VOZXh0ID0gIlx1Mjc2ZiIsCiAgICBwYWdlUHJldmlvdXNMYWJlbCA9ICJQw6FnaW5hIGFudGVyaW9yIiwKICAgIHBhZ2VOZXh0TGFiZWwgPSAiUMOhZ2luYSBzaWd1aWVudGUiCiAgKQopCgpgYGAKCiMjIyA0LjIuIEdSw4FGSUNBUwpQYXJhIGxvcyBncsOhZmljb3MsIGhhcmVtb3MgMyBncsOhZmljb3MgZGUgYmFycmFzLiBFbCBwcmltZXJvIGVzdGFyw6EgcmVsYWNpb25hZG8gY29uIGxvcyAxMCBhcGVsbGlkb3MgbcOhcyBmcmVjdWVudGVzLCBlbCBzZWd1bmRvIGNvbiBsb3MgMTAgbm9tYnJlcyBtw6FzIGZyZWN1ZW50ZXMgeSBlbCB0ZXJjZXJvIHNlcsOhIHVuIGdyw6FmaWNvIGRlIGxvcyAxMCBub21icmVzIG1lbm9zIGNvbXVuZXMgeSBsb3MgMTAgcXVlIG3DoXMuCgpQcmltZXJvLCBuZWNlc2l0YXJlbW9zIHRyYW5zZm9ybWFyIGxvcyBkYXRvcwpgYGB7ciBlY2hvPSBUUlVFLCBldmFsPVRSVUV9CiNBUEVMTElET1MKZGZfYXBlbGxpZG9zIDwtIGRmX2FwZWxsaWRvczEgJT4lIHNlbGVjdChBcGVsbGlkbywgRnJlY18xZXJfQXBlbGxpZG8sIEZyZWNfMm9fQXBlbGxpZG8pICU+JSBtdXRhdGUoRnJlY19Ub3RhbD0gRnJlY18xZXJfQXBlbGxpZG8gKyBGcmVjXzJvX0FwZWxsaWRvKSAlPiUgc2xpY2VfbWF4KEZyZWNfVG90YWwsIG49MTApICU+JSBtdXRhdGUoQXBlbGxpZG8gPSBmb3JjYXRzOjphc19mYWN0b3IoQXBlbGxpZG8pKSAlPiUgbXV0YXRlKEFwZWxsaWRvID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoQXBlbGxpZG8sIEZyZWNfVG90YWwpKQoKCnAgPC0gZ2dwbG90KGRmX2FwZWxsaWRvcywgYWVzKEFwZWxsaWRvLCBGcmVjX1RvdGFsKSkgKyBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsgY29vcmRfZmxpcCgpCgoKI05PTUJSRVMKZGZfbm9tYnJlcyA8LSBmdWxsX2pvaW4oZGZfbm9tYnJlLCBkZl9ub21icmUxKQoKZGZfbm9tYnJlczMgPC1kZl9ub21icmVzICU+JSBzZWxlY3QoTm9tYnJlLCBGcmVjdWVuY2lhKSAlPiUgc2xpY2VfbWF4KEZyZWN1ZW5jaWEsIG49MTApICU+JSBtdXRhdGUoTm9tYnJlID0gZm9yY2F0czo6YXNfZmFjdG9yKE5vbWJyZSkpICU+JSBtdXRhdGUoTm9tYnJlID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoTm9tYnJlLCBGcmVjdWVuY2lhKSkKCnMgPC0gZ2dwbG90KGRmX25vbWJyZXMzLCBhZXMoTm9tYnJlLCBGcmVjdWVuY2lhKSkgKyBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsgY29vcmRfZmxpcCgpCgoKIzEwIE3DgVMgRlJFQ1VFTlRFUyBZIDEwIFFVRSBNRU5PUwpkZl9ub21icmVzX2VkYWRtZWRpYSA8LSBkZl9ub21icmVzICU+JSBzZWxlY3QoTm9tYnJlLCBgRWRhZCBNZWRpYSAoKilgKSAlPiUgYXJyYW5nZShkZXNjKGBFZGFkIE1lZGlhICgqKWApKSAlPiUKICBzbGljZShjKDEsMiwzLDQsNSw2LDcsOCw5LDEwLG4oKS05LG4oKS04LG4oKS03LG4oKS02LG4oKS01LG4oKS00LG4oKS0zLG4oKS0yLG4oKS0xLCBuKCkpKSU+JQogIG11dGF0ZShOb21icmUgPSBmb3JjYXRzOjphc19mYWN0b3IoTm9tYnJlKSkgJT4lIG11dGF0ZShOb21icmUgPSBmb3JjYXRzOjpmY3RfcmVvcmRlcihOb21icmUsIGBFZGFkIE1lZGlhICgqKWApKQoKciA8LSBnZ3Bsb3QoZGZfbm9tYnJlc19lZGFkbWVkaWEsIGFlcyhOb21icmUsIGBFZGFkIE1lZGlhICgqKWApKSArIGdlb21fY29sKGZpbGw9InN0ZWVsYmx1ZSIpICsgY29vcmRfZmxpcCgpCgpgYGAKCk1vc3RyYW1vcyBsb3MgZ3LDoWZpY29zOgpgYGB7ciBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CnAgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIsCiAgc2l6ZSA9IDEpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKHNpemUgPSAxKSwKICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSwgZmFjZSA9ICJib2xkLml0YWxpYyIsCiAgICBjb2xvdXIgPSAiZ3JheTI1IiksIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LAogICAgICBoanVzdCA9IDAuNSwgdmp1c3QgPSAyLDUpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJsaWdodHllbGxvdyIsCiAgICAgICAgY29sb3VyID0gTkEpKSArbGFicyh0aXRsZSA9ICJMT1MgMTAgQVBFTExJRE9TIE3DgVMgRlJFQ1VFTlRFUyIsIGNhcHRpb24gPSAiRGF0b3MgcHJvdmVuaWVudGVzIGRlbCBJTkUiKQoKYGBgCgpgYGB7ciBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CgpzICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShzaXplID0gMC45KSwKICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjkpLAogIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLAogICAgZmFjZSA9ICJib2xkLml0YWxpYyIpLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLAogICAgICBmYWNlID0gImJvbGQuaXRhbGljIiksIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkLml0YWxpYyIsCiAgICAgICAgaGp1c3QgPSAwLjUsIHZqdXN0ID0gMS41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXk4NyIsCiAgICAgICAgICBzaXplID0gMC44KSwgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiYWxpY2VibHVlIiwKICAgICAgICAgICAgc2l6ZSA9IDAuNikpICtsYWJzKHRpdGxlID0gIkxPUyAxMCBOT01CUkVTIE3DgVMgRlJFQ1VFTlRFUyIsICBjYXB0aW9uID0gIkRhdG9zIHByb3ZlbmllbnRlcyBkZWwgSU5FIikKCmBgYAoKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9VFJVRX0KZ2dwbG90bHkocikKYGBgCgoKIyMjIDQuMy4gTUFQQVMKQ2FyZ2FyZW1vcyBwcmltZXJvIGxhcyBnZW9tZXRyw61hcyBkZSBsYSBjYXJwZXRhIERhdG9zCmBgYHtyIGVjaG89VFJVRSwgZXZhbD1UUlVFfQpsb2FkKCIuL0RhdG9zL2dlb21ldHJpYXNfY2xhc2VfMTAuUkRhdGEiKQpgYGAKWSBhaG9yYSBoYXJlbW9zIHVuIG1hcGEgcGFyYSBsYSBmcmVjdWVuY2lhIHBvciBwcm92aW5jaWFzIGRlbCBub21icmUgZGUgRGFuaWVsOgpgYGB7ciBlY2hvPVRSVUUsIGV2YWw9VFJVRX0KCiNIYWNlbW9zIHVuIG1hcGEgZGUgY29yb3BsZXRhcyBkZWwgcGHDrXMgcGFyYSBlbCB0b3RhbCBkZWwgbm9tYnJlICJEYW5pZWwiCmRmRGFuaWVsIDwtIGZ1bGxfam9pbihkZl9EYW5pZWwsIFByb3ZpbmNpYXMsIGJ5ID0gYygiUHJvdmluY2lhIiA9ICJOb21icmVQcm92IikpCgpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9VFJVRX0KZ2dwbG90KGRhdGEgPSBkZkRhbmllbCwgYWVzKGdlb21ldHJ5ID0gZ2VvbWV0cnkpKSArIGdlb21fc2YoYWVzKGZpbGwgPSBUb3RhbCkpICsgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gImluZmVybm8iLCBkaXJlY3Rpb24gPSAtMSkKYGBgCgpZIGFob3JhIG90cm8gbWFwYSBwYXJhIGxhIGZyZWN1ZW5jaWEgcG9yIHByb3ZpbmNpYXMgZGVsIG5vbWJyZSBkZSBMYXVyYToKYGBge3IgZWNobz1UUlVFLCBldmFsPVRSVUV9CgojSGFjZW1vcyBvdHJvIG1hcGEgZGUgY29yb3BsZXRhcyBwYXJhIGVsIHRvdGFsIGRlbCBub21icmUgIkxhdXJhIi4KZGZMYXVyYTwtZnVsbF9qb2luKGRmX0xhdXJhLCBQcm92aW5jaWFzLCBieSA9IGMoIlByb3ZpbmNpYSIgPSAiTm9tYnJlUHJvdiIpKQoKYGBgCgpgYGB7ciBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CmdncGxvdChkYXRhID0gZGZMYXVyYSwgYWVzKGdlb21ldHJ5ID0gZ2VvbWV0cnkpKSArIGdlb21fc2YoYWVzKGZpbGwgPSBUb3RhbCkpICsgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gImluZmVybm8iLCBkaXJlY3Rpb24gPSAtMSkKYGBgCgoKCiMjIDUuIENvbmNsdXNpw7NuCgpMYXMgY29uY2x1c2lvbmVzIHNvbiAuLi4KCgoKIyMgUmVmZXJlbmNpYXMKClBhcmEgbGEgcmVhbGl6YWNpw7NuIGRlbCB0cmFiYWpvIGhlIHV0aWxpemFkbzoKCi0gCgotIAoKCi0tLS0tLS0tLS0tLS0tLS0KCjxicj48YnI+CgpQYXJhIGFjYWJhciBlc3RlIGNodW5rIHBhcmEgaW5jbHVpciB0dSBgc2Vzc2lvbiBpbmZvYDoKCmBgYHtyfQpzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkgJT4lIGRldGFpbHM6OmRldGFpbHMoc3VtbWFyeSA9ICdjdXJyZW50IHNlc3Npb24gaW5mbycpIApgYGAK